package com.budweiser.ems.zuul.controller;

import com.budweiser.ems.zuul.feign.LogClient;
import com.budweiser.ems.zuul.feign.Oauth2Client;
import com.budweiser.model.log.Log;
import com.budweiser.model.oauth.SystemClientInfo;
import com.budweiser.model.user.constants.CredentialType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 登陆、刷新token、退出
 *
 * @author 小威老师
 */
@Slf4j
@RestController
public class TokenController {
	@Autowired
	private Oauth2Client oauth2Client;
	@Autowired
	private LogClient logClient;

	/**
	 * 系统登陆<br>
	 * 根据用户名登录<br>
	 * 采用oauth2密码模式获取access_token和refresh_token
	 *
	 * @param username
	 * @param password
	 * @return
	 */
	@PostMapping("/sys/login")
	public Map<String, Object> login(String username, String password) {
		Map<String, String> parameters = new HashMap<>();
		parameters.put(OAuth2Utils.GRANT_TYPE, "password");
		parameters.put(OAuth2Utils.CLIENT_ID, SystemClientInfo.CLIENT_ID);
		parameters.put("client_secret", SystemClientInfo.CLIENT_SECRET);
		parameters.put(OAuth2Utils.SCOPE, SystemClientInfo.CLIENT_SCOPE);
		// parameters.put("username", username);
		// 为了支持多类型登录，这里在username后拼装上登录类型
		parameters.put("username", username + "|" + CredentialType.USERNAME.name());
		parameters.put("password", password);
		parameters.put("expires_in", "10");
		Map<String, Object> tokenInfo = oauth2Client.postAccessToken(parameters);
		System.out.println(tokenInfo.get("access_token"));
		saveLoginLog(username, "用户名密码登陆");
		return tokenInfo;
	}

	/**
	 * 短信登录
	 *
	 * @param phone
	 * @param key
	 * @param code
	 * @return
	 */
	@PostMapping("/sys/login-sms")
	public Map<String, Object> smsLogin(String phone, String key, String code) {
		Map<String, String> parameters = new HashMap<>();
		parameters.put(OAuth2Utils.GRANT_TYPE, "password");
		parameters.put(OAuth2Utils.CLIENT_ID, SystemClientInfo.CLIENT_ID);
		parameters.put("client_secret", SystemClientInfo.CLIENT_SECRET);
		parameters.put(OAuth2Utils.SCOPE, SystemClientInfo.CLIENT_SCOPE);
		// 为了支持多类型登录，这里在username后拼装上登录类型，同时为了校验短信验证码，我们也拼上code等
		parameters.put("username", phone + "|" + CredentialType.PHONE.name() + "|" + key + "|" + code + "|"
				+ DigestUtils.md5Hex(key + code));
		// 短信登录无需密码，但security底层有密码校验，我们这里将手机号作为密码，认证中心采用同样规则即可
		parameters.put("password", phone);

		Map<String, Object> tokenInfo = oauth2Client.postAccessToken(parameters);
		saveLoginLog(phone, "手机号短信登陆");

		return tokenInfo;
	}

	/**
	 * 登陆日志
	 *
	 * @param username
	 */
	private void saveLoginLog(String username, String remark) {
		log.info("{}登陆", username);
		// 异步
		CompletableFuture.runAsync(() -> {
			try {
				Log log = Log.builder().username(username).module("登陆").remark(remark).createTime(new Date()).build();
				logClient.save(log);
			} catch (Exception e) {
				// do nothing
			}

		});
	}

	/**
	 * 系统刷新refresh_token
	 *
	 * @param refresh_token
	 * @return
	 */
	@PostMapping("/sys/refresh_token")
	public Map<String, Object> refresh_token(String refresh_token) {
		Map<String, String> parameters = new HashMap<>();
		parameters.put(OAuth2Utils.GRANT_TYPE, "refresh_token");
		parameters.put(OAuth2Utils.CLIENT_ID, SystemClientInfo.CLIENT_ID);
		parameters.put("client_secret", SystemClientInfo.CLIENT_SECRET);
		parameters.put(OAuth2Utils.SCOPE, SystemClientInfo.CLIENT_SCOPE);
		parameters.put("refresh_token", refresh_token);

		return oauth2Client.postAccessToken(parameters);
	}

	/**
	 * 退出
	 *
	 * @param access_token
	 */
	@GetMapping("/sys/logout")
	public void logout(String access_token, @RequestHeader(required = false, value = "Authorization") String token) {
		if (StringUtils.isBlank(access_token)) {
			if (StringUtils.isNoneBlank(token)) {
				access_token = token.substring(OAuth2AccessToken.BEARER_TYPE.length() + 1);
			}
		}
		oauth2Client.removeToken(access_token);
	}
}
